package serverManager;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import db_manager.Dir;
import db_manager.DirManager;
import db_manager.Manager;

/**
 * this class wait for users to create or delete a directory from their dropboxes and then 
 * react accordingly
 */
public class UpdateDir extends Thread
{
	ServerSocket serverSocket=null;
	Socket clientSocket=null;
	boolean serverIsUp;
	Manager manager;
	
	/**
	 * the constructor of this class
	 * @throws IOException
	 */
	public UpdateDir() throws IOException
	{
		manager = Manager.getInstance();
		serverIsUp = true;
		serverSocket = new ServerSocket(4567);
	}

	/**
	 * the Thread execution function
	 */
	public void run()
	{
		BufferedReader in = null;
		String user_name, dir_name, isCreate;
		File sessionFile = new File("C:\\Program Files\\m&l_dropbox_server\\hibernate.cfg.xml");
		// Opening a new session factory - for connection with DB
		SessionFactory sessionFactory = new Configuration().configure(sessionFile).buildSessionFactory();
		try
		{
			// as long as the server program is up keep running
			while(serverIsUp)
			{			
				// waits for an update
				clientSocket=serverSocket.accept();
				//creating session for connecting to DB
				Session session = sessionFactory.openSession();

				in=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
				PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),true);
				dir_name = in.readLine(); 
				user_name=in.readLine();
				isCreate = in.readLine();
				// the case that a new dir was created
				if(isCreate.equals("create"))
				{
					long dir_id = manager.nextDirId(session);
					DirManager dm = new DirManager(session);
					Dir dir = new Dir();
					dir.setDir_name(dir_name);
					dir.setUser_id(manager.checkUserId(session, user_name));
					dir.setDir_id(dir_id);
					// updating the DB
					dm.saveDir(dir);
					session.flush();
					out.println("ok");
				}
				// // the case that a dir was deleted
				else
				{
					boolean doesShared = manager.checkShared(session, dir_name, user_name);
					// the case that this folder id shared - delete only from DB
					if(doesShared)
					{
						// updating the DB
						deleteDir(session, dir_name, user_name);	
					}
					// the case that the folder is not shared - delete also the files inside
					else
					{
						manager.deleteFilesFromDir(session, dir_name, user_name);
						deleteDir(session, dir_name, user_name);
					}
					out.println("ok");
				}
			}
		}
		catch(Exception e) {}
	}

	/*
	 * this function delete the dir from the DB
	 * @param session
	 * @param dir_name
	 * @param user_name
	 */
	private void deleteDir(Session session, String dir_name, String user_name) 
	{
		DirManager dm = new DirManager(session);
		Query query = session.createQuery("from db_manager.Dir");
		@SuppressWarnings("unchecked")
		List <Dir>list = query.list();
		Iterator<Dir> it=list.iterator();
		Dir dir;
		//run over all the tuples in DB
		while (it.hasNext())
		{
			dir=it.next();
			// the case that we found the dir that needs to be deleted
			if (dir.getDir_name().equals(dir_name) && dir.getUser_id() == manager.checkUserId(session, user_name))
			{
				dm.deleteDir(dir);
			}			
		}
		session.flush();
	}

	/**
	 * ending this Thread
	 */
	public void shutDownServer()
	{
		try
		{
			// the case that this socket is open
			if (clientSocket != null)
			{
				clientSocket.close();
			}
			// the case that this server socket is open
			if (serverSocket != null) 
			{
				serverSocket.close();
			}
		}
		catch(Exception e) {}
		serverIsUp = false;
	}
}
